/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.commonmodel.spi;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.inspur.edp.cef.api.manager.serialize.CefSerializeContext;
import com.inspur.edp.cef.entity.entity.ICefData;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.entity.entity.IEntityDataCollection;
import com.inspur.edp.cef.spi.extend.entity.ICefAddedChildEntityExtend;
import com.inspur.edp.cef.spi.extend.entity.ICefEntityExtend;
import com.inspur.edp.cef.spi.jsonser.abstractcefchange.AbstractCefDataSerItem;
import com.inspur.edp.cef.spi.jsonser.base.StringUtils;
import com.inspur.edp.cef.spi.jsonser.entity.AbstractEntitySerializerItem;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.var;

public abstract class AbstractEntityDataSerializer
    extends com.inspur.edp.cef.spi.jsonser.abstractcefchange.AbstractCefDataSerializer {
  private String objectCode;
  private boolean isRoot;

  protected AbstractEntityDataSerializer(
      String objectCode, boolean isRoot, List<AbstractEntitySerializerItem> serializers) {
    super(serializers);
    this.objectCode = objectCode;
    this.isRoot = isRoot;
  }

  private AbstractEntityDataSerializer innerGetChildConvertor(String nodeCode){
    for(Object item : getExtendList()) {
      List<ICefAddedChildEntityExtend> addedChilds = ((ICefEntityExtend)item).getAddedChilds();
      if(addedChilds == null){
        continue;
      }
      for(ICefAddedChildEntityExtend addedChild : addedChilds){
        if(addedChild.getNodeCode().equals(nodeCode)){
          return (AbstractEntityDataSerializer)addedChild.getDataSerializer();
        }
      }
    }
    return getChildConvertor(nodeCode);
  }

  protected abstract AbstractEntityDataSerializer getChildConvertor(String childCode);
  public  AbstractEntityDataSerializer getChildDataConvertor(String childCode){
    return getChildConvertor(childCode);
  }
  @Override
  protected void writeDataInfo(JsonGenerator writer, ICefData data, SerializerProvider serializer)
      throws IOException {
    // writer.WritePropertyName("ID");
    // writer.WriteValue(((IEntityData)data).ID);
    super.writeDataInfo(writer, data, serializer);
    writeChildObjects(writer, (IEntityData) data, serializer);
  }

  private void writeChildObjects(
      JsonGenerator writer, IEntityData data, SerializerProvider serializer) throws IOException {
    HashMap<String, IEntityDataCollection> childs = data.getChilds();
    if (childs == null || childs.size() == 0) {
      return;
    }
for (Map.Entry<String, IEntityDataCollection> item : childs.entrySet()) {
      writeChildObjects(writer, item.getKey(), item.getValue(), serializer);
    }
  }

  private void writeChildObjects(
      JsonGenerator writer,
      String childCode,
      IEntityDataCollection childs,
      SerializerProvider serializer)
      throws IOException {

    writer.writeFieldName(StringUtils.toCamelCase(childCode)+"s");
    writer.writeStartArray();
    if (childs != null && childs.size() != 0) {
      AbstractEntityDataSerializer childConvertor = innerGetChildConvertor(childCode);
      if(childConvertor != null) {
        List<ICefEntityExtend> extendList = getExtendList();
        addExtendList(childConvertor, extendList, childCode);
        childConvertor.setCefSerializeContext(context);
      }
      for (IEntityData item : childs) {
        if(childConvertor == null)
          writer.writeObject(item);
        else
          childConvertor.writeJson(writer, item, serializer);
      }
    }
    writer.writeEndArray();
  }

    private void addExtendList(AbstractEntityDataSerializer childConvertor,List<ICefEntityExtend> extendList,String childCode) {
        if(extendList == null || extendList.size() <1)
            return;
        for(ICefEntityExtend extend : extendList){
            var childEntity = extend.getChildEntity(childCode);
            if(childEntity != null)
                childConvertor.addExtend(childEntity);
        }
    }

    private CefSerializeContext context;
  @Override
  public void setCefSerializeContext(CefSerializeContext context) {
    super.setCefSerializeContext(context);
    this.context = context;
  }
}
